home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_emacs.idb / usr / freeware / share / emacs / 19.34 / lisp / finder.el.z / finder.el
Encoding:
Text File  |  1998-10-28  |  9.9 KB  |  300 lines

  1. ;;; finder.el --- topic & keyword-based code finder
  2.  
  3. ;; Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
  6. ;; Created: 16 Jun 1992
  7. ;; Version: 1.0
  8. ;; Keywords: help
  9.  
  10. ;; This file is part of GNU Emacs.
  11.  
  12. ;; GNU Emacs is free software; you can redistribute it and/or modify
  13. ;; it under the terms of the GNU General Public License as published by
  14. ;; the Free Software Foundation; either version 2, or (at your option)
  15. ;; any later version.
  16.  
  17. ;; GNU Emacs is distributed in the hope that it will be useful,
  18. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. ;; GNU General Public License for more details.
  21.  
  22. ;; You should have received a copy of the GNU General Public License
  23. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  24. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25. ;; Boston, MA 02111-1307, USA.
  26.  
  27. ;;; Commentary:
  28.  
  29. ;; This mode uses the Keywords library header to provide code-finding
  30. ;; services by keyword.
  31. ;;
  32. ;; Things to do:
  33. ;;    1. Support multiple keywords per search.  This could be extremely hairy;
  34. ;; there doesn't seem to be any way to get completing-read to exit on
  35. ;; an EOL with no substring pending, which is what we'd want to end the loop.
  36. ;;    2. Search by string in synopsis line?
  37. ;;    3. Function to check finder-package-info for unknown keywords.
  38.  
  39. ;;; Code:
  40.  
  41. (require 'lisp-mnt)
  42. (require 'finder-inf)
  43.  
  44. ;; Local variable in finder buffer.
  45. (defvar finder-headmark)
  46.  
  47. (defvar finder-known-keywords
  48.   '(
  49.     (abbrev    . "abbreviation handling, typing shortcuts, macros")
  50.     (bib    . "code related to the `bib' bibliography processor")
  51.     (c        . "support for the C language and related languages")
  52.     (calendar    . "calendar and time management support")
  53.     (comm    . "communications, networking, remote access to files")
  54.     (data    . "support editing files of data")
  55.     (docs    . "support for Emacs documentation")
  56.     (emulations    . "emulations of other editors")
  57.     (extensions    . "Emacs Lisp language extensions")
  58.     (faces    . "support for multiple fonts")
  59.     (frames     . "support for Emacs frames and window systems")
  60.     (games    . "games, jokes and amusements")
  61.     (hardware    . "support for interfacing with exotic hardware")
  62.     (help    . "support for on-line help systems")
  63.     (hypermedia . "support for links between text or other media types")
  64.     (i18n    . "internationalization and alternate character-set support")
  65.     (internal    . "code for Emacs internals, build process, defaults")
  66.     (languages    . "specialized modes for editing programming languages")
  67.     (lisp    . "Lisp support, including Emacs Lisp")
  68.     (local    . "code local to your site")
  69.     (maint    . "maintenance aids for the Emacs development group")
  70.     (mail    . "modes for electronic-mail handling")
  71.     (matching    . "various sorts of searching and matching")
  72.     (mouse    . "mouse support")
  73.     (news    . "support for netnews reading and posting")
  74.     (oop        . "support for object-oriented programming")
  75.     (outlines   . "support for hierarchical outlining")
  76.     (processes    . "process, subshell, compilation, and job control support")
  77.     (terminals    . "support for terminal types")
  78.     (tex    . "code related to the TeX formatter")
  79.     (tools    . "programming tools")
  80.     (unix    . "front-ends/assistants for, or emulators of, UNIX features")
  81.     (vms    . "support code for vms")
  82.     (wp        . "word processing")
  83.     ))
  84.  
  85. (defvar finder-mode-map nil)
  86. (or finder-mode-map
  87.     (let ((map (make-sparse-keymap)))
  88.       (define-key map " "    'finder-select)
  89.       (define-key map "f"    'finder-select)
  90.       (define-key map "\C-m"    'finder-select)
  91.       (define-key map "?"    'finder-summary)
  92.       (define-key map "q"    'finder-exit)
  93.       (define-key map "d"    'finder-list-keywords)
  94.       (setq finder-mode-map map)))
  95.  
  96.  
  97. ;;; Code for regenerating the keyword list.
  98.  
  99. (defvar finder-package-info nil
  100.   "Assoc list mapping file names to description & keyword lists.")
  101.  
  102. (defun finder-compile-keywords (&rest dirs)
  103.   "Regenerate the keywords association list into the file `finder-inf.el'.
  104. Optional arguments are a list of Emacs Lisp directories to compile from; no
  105. arguments compiles from `load-path'."
  106.   (save-excursion
  107.     (let ((processed nil))
  108.       (find-file "finder-inf.el")
  109.       (erase-buffer)
  110.       (insert ";;; finder-inf.el --- keyword-to-package mapping\n")
  111.       (insert ";; Keywords: help\n")
  112.       (insert ";;; Commentary:\n")
  113.       (insert ";; Don't edit this file.  It's generated by finder.el\n\n")
  114.       (insert ";;; Code:\n")
  115.       (insert "\n(setq finder-package-info '(\n")
  116.       (mapcar
  117.        (lambda (d)
  118.      (mapcar
  119.       (lambda (f) 
  120.         (if (and (string-match "^[^=].*\\.el$" f)
  121.              (not (member f processed)))
  122.         (let (summary keystart keywords)
  123.           (setq processed (cons f processed))
  124.           (save-excursion
  125.             (set-buffer (get-buffer-create "*finder-scratch*"))
  126.             (buffer-disable-undo (current-buffer))
  127.             (erase-buffer)
  128.             (insert-file-contents
  129.              (concat (file-name-as-directory (or d ".")) f))
  130.             (setq summary (lm-synopsis))
  131.             (setq keywords (lm-keywords)))
  132.           (insert
  133.            (format "    (\"%s\"\n        " f))
  134.           (prin1 summary (current-buffer))
  135.           (insert
  136.            "\n        ")
  137.           (setq keystart (point))
  138.           (insert
  139.            (if keywords (format "(%s)" keywords) "nil")
  140.            ")\n")
  141.           (subst-char-in-region keystart (point) ?, ? )
  142.           )))
  143.       (directory-files (or d "."))))
  144.        (or dirs load-path))
  145.       (insert "))\n\n(provide 'finder-inf)\n\n;;; finder-inf.el ends here\n")
  146.       (kill-buffer "*finder-scratch*")
  147.       (eval-current-buffer) ;; So we get the new keyword list immediately
  148.       (basic-save-buffer))))
  149.  
  150. (defun finder-compile-keywords-make-dist ()
  151.   "Regenerate `finder-inf.el' for the Emacs distribution."
  152.   (finder-compile-keywords default-directory))
  153.  
  154. ;;; Now the retrieval code
  155.  
  156. (defun finder-insert-at-column (column &rest strings)
  157.   "Insert list of STRINGS, at column COLUMN."
  158.   (if (> (current-column) column) (insert "\n"))
  159.   (move-to-column column)
  160.   (let ((col (current-column)))
  161.     (if (< col column)
  162.     (indent-to column)
  163.       (if (and (/= col column)
  164.            (= (preceding-char) ?\t))
  165.       (let (indent-tabs-mode)
  166.         (delete-char -1)
  167.             (indent-to col)
  168.             (move-to-column column)))))
  169.   (apply 'insert strings))
  170.  
  171. (defun finder-list-keywords ()
  172.   "Display descriptions of the keywords in the Finder buffer."
  173.   (interactive)
  174.   (setq buffer-read-only nil)
  175.   (erase-buffer)
  176.   (mapcar
  177.    (lambda (assoc)
  178.      (let ((keyword (car assoc)))
  179.        (insert (symbol-name keyword))
  180.        (finder-insert-at-column 14 (concat (cdr assoc) "\n"))
  181.        (cons (symbol-name keyword) keyword)))
  182.    finder-known-keywords)
  183.   (goto-char (point-min))
  184.   (setq finder-headmark (point))
  185.   (setq buffer-read-only t)
  186.   (set-buffer-modified-p nil)
  187.   (balance-windows)
  188.   (finder-summary))
  189.  
  190. (defun finder-list-matches (key)
  191.   (setq buffer-read-only nil)
  192.   (erase-buffer)
  193.   (let ((id (intern key)))
  194.     (insert
  195.      "The following packages match the keyword `" key "':\n\n")
  196.     (setq finder-headmark (point))
  197.     (mapcar
  198.      (lambda (x)
  199.        (if (memq id (car (cdr (cdr x))))
  200.        (progn
  201.          (insert (car x))
  202.          (finder-insert-at-column 16 (concat (car (cdr x)) "\n")))))
  203.      finder-package-info)
  204.     (goto-char (point-min))
  205.     (forward-line)
  206.     (setq buffer-read-only t)
  207.     (set-buffer-modified-p nil)
  208.     (shrink-window-if-larger-than-buffer)
  209.     (finder-summary)))
  210.  
  211. ;; Search for a file named FILE the same way `load' would search.
  212. (defun finder-find-library (file)
  213.   (if (file-name-absolute-p file)
  214.       file
  215.     (let ((dirs load-path)
  216.       found)
  217.       (while (and dirs (not found))
  218.     (if (file-exists-p (expand-file-name (concat file ".el") (car dirs)))
  219.         (setq found (expand-file-name file (car dirs)))
  220.       (if (file-exists-p (expand-file-name file (car dirs)))
  221.           (setq found (expand-file-name file (car dirs)))))
  222.     (setq dirs (cdr dirs)))
  223.       found)))
  224.  
  225. (defun finder-commentary (file)
  226.   (interactive)
  227.   (let* ((str (lm-commentary (finder-find-library file))))
  228.     (if (null str)
  229.     (error "Can't find any Commentary section"))
  230.     (pop-to-buffer "*Finder*")
  231.     (setq buffer-read-only nil)
  232.     (erase-buffer)
  233.     (insert str)
  234.     (goto-char (point-min))
  235.     (delete-blank-lines)
  236.     (goto-char (point-max))
  237.     (delete-blank-lines)
  238.     (goto-char (point-min))
  239.     (while (re-search-forward "^;+ ?" nil t)
  240.       (replace-match "" nil nil))
  241.     (goto-char (point-min))
  242.     (setq buffer-read-only t)
  243.     (set-buffer-modified-p nil)
  244.     (shrink-window-if-larger-than-buffer)
  245.     (finder-summary)))
  246.  
  247. (defun finder-current-item ()
  248.   (if (and finder-headmark (< (point) finder-headmark))
  249.       (error "No keyword or filename on this line")
  250.     (save-excursion
  251.       (beginning-of-line)
  252.       (current-word))))
  253.  
  254. (defun finder-select ()
  255.   (interactive)
  256.   (let ((key (finder-current-item)))
  257.     (if (string-match "\\.el$" key)
  258.     (finder-commentary key)
  259.       (finder-list-matches key))))
  260.  
  261. (defun finder-by-keyword ()
  262.   "Find packages matching a given keyword."
  263.   (interactive)
  264.   (finder-mode)
  265.   (finder-list-keywords))
  266.  
  267. (defun finder-mode ()
  268.   "Major mode for browsing package documentation.
  269. \\<finder-mode-map>
  270. \\[finder-select]    more help for the item on the current line
  271. \\[finder-exit]    exit Finder mode and kill the Finder buffer.
  272. "
  273.   (interactive)
  274.   (pop-to-buffer "*Finder*")
  275.   (setq buffer-read-only nil)
  276.   (erase-buffer)
  277.   (use-local-map finder-mode-map)
  278.   (set-syntax-table emacs-lisp-mode-syntax-table)
  279.   (setq mode-name "Finder")
  280.   (setq major-mode 'finder-mode)
  281.   (make-local-variable 'finder-headmark)
  282.   (setq finder-headmark nil))
  283.  
  284. (defun finder-summary ()
  285.   "Summarize basic Finder commands."
  286.   (interactive)
  287.   (message "%s"
  288.    (substitute-command-keys
  289.     "\\<finder-mode-map>\\[finder-select] = select, \\[finder-list-keywords] = to finder directory, \\[finder-exit] = quit, \\[finder-summary] = help")))
  290.  
  291. (defun finder-exit ()
  292.   "Exit Finder mode and kill the buffer"
  293.   (interactive)
  294.   (delete-window)
  295.   (kill-buffer "*Finder*"))
  296.  
  297. (provide 'finder)
  298.  
  299. ;;; finder.el ends here
  300.